package com.assembler.app;

import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.swing.JFrame;

import org.apache.commons.io.FileUtils;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RefineryUtilities;

import com.assembler.app.debruij.DeBruijnGraph;
import com.assembler.app.genome.Genome;
import com.assembler.app.genome.GenomeFileHelper;

public class FindPathsMainApp extends JFrame {
	public static XYDataset dataset;

	public FindPathsMainApp(String applicationTitle) {
		super(applicationTitle);
		// This will create the dataset

		final JFreeChart chart = createChart(dataset);
		final ChartPanel chartPanel = new ChartPanel(chart);
		chartPanel.setPreferredSize(new java.awt.Dimension(2000, 1500));
		setContentPane(chartPanel);

	}

	private JFreeChart createChart(XYDataset dataset2) {
		// create the chart...
		final JFreeChart chart = ChartFactory.createXYLineChart("Repeats In E-Coli Genome", // chart
																							// title
				"genome", // x axis label
				"# superbubble", // y axis label
				dataset, // data
				PlotOrientation.VERTICAL, false, // include legend
				true, // tooltips
				false // urls
				);

		// NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...
		chart.setBackgroundPaint(Color.white);

		// final StandardLegend legend = (StandardLegend) chart.getLegend();
		// legend.setDisplaySeriesShapes(true);

		// get a reference to the plot for further customisation...
		final XYPlot plot = chart.getXYPlot();
		plot.setBackgroundPaint(Color.lightGray);
		// plot.setAxisOffset(new Spacer(Spacer.ABSOLUTE, 5.0, 5.0, 5.0, 5.0));
		plot.setDomainGridlinePaint(Color.white);
		plot.setRangeGridlinePaint(Color.white);

		final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
		renderer.setBaseShapesVisible(true);

        renderer.setBaseShapesFilled (true);
		plot.setRenderer(renderer);

		// change the auto tick unit selection to integer units only...
		final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
		rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
		// OPTIONAL CUSTOMISATION COMPLETED.

		return chart;

	}

	public static void main(String[] args) {
		superbubbleParsing();
		final FindPathsMainApp demo = new FindPathsMainApp("E.Coli Genome Detecting Superbubbles");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);

	}

	private static void superbubbleParsing() {
		int k = 20;
		GenomeFileHelper genomeFileHelper = new GenomeFileHelper();
		long start = System.currentTimeMillis();
		Genome genome = genomeFileHelper.readFromTxtFile("ecoli_genome.txt");
		System.out.println("1. File read took " + (System.currentTimeMillis() - start));
		System.out.println("genome length = " + genome.getGenom().length());
		String pairsAsString = null;
		String pairsAsString2 = null;
		try {
			pairsAsString = FileUtils.readFileToString(new File("Pairs_ecoli_genome_20 kmers.txt"));
			pairsAsString2 = pairsAsString.replaceAll("[\n\r]", "");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		StringTokenizer stringTokenizer = new StringTokenizer(pairsAsString2, "|");
		List<String> pairs = new LinkedList<String>();
		while (stringTokenizer.hasMoreElements()) {
			pairs.add(stringTokenizer.nextToken());
		}
		Map<String, String> pairsMap = new HashMap<>(pairs.size());
		for (String pair : pairs) {
			String startString = pair.substring(0, pair.indexOf('-'));
			String endString = pair.substring(pair.indexOf('-') + 1, pair.length());
			pairsMap.put(startString.trim(), endString.trim());
		}

		start = System.currentTimeMillis();

		List<String> kmers = GenomAssembler.buildKMers(genome.getGenom(), k);
		System.out.println("2. 'GenomAssembler.buildKMers' took "
				+ (System.currentTimeMillis() - start));

		start = System.currentTimeMillis();
		DeBruijnGraph graph = GenomAssembler.getDeBruijnGraph(kmers, true);
		System.out.println("3. 'GenomAssembler.getDeBruijnGraph' took "
				+ (System.currentTimeMillis() - start));

		// Map<String, String> testmap = new HashMap<>(1);
		// testmap.put("AGC", "TAG");
		// graph.paths = null;
		// graph.findPath("AGC", "TAG", "");
		// for (String path : graph.paths) {
		// System.out.println(path);
		// String currentPath = convertPathToGenomeSubString(path);
		// System.out.println(currentPath);
		// findAllIndexesForPathOccurence(genome.getGenom(),currentPath);
		//
		// }
		XYSeriesCollection datasetTmp = new XYSeriesCollection();
		long superbubbleNumber = 0;
		System.out.println("genome length = " + genome.getGenom().length());
		for (Map.Entry<String, String> entry : pairsMap.entrySet()) {
			superbubbleNumber++;
			System.out.println("Starting path search for superbubble #" + superbubbleNumber + ": ("
					+ entry.getKey() + "," + entry.getValue() + ")");
			System.out.println();
			graph.paths = null;
			graph.findPath(entry.getKey(), entry.getValue(), "");
			long pathNumber = 0;
			for (String path : graph.paths) {
				pathNumber++;
				System.out.println("All nodes for path #" + pathNumber + path);
				String currentPath = convertPathToGenomeSubString(path);
				System.out.println("The genome substring : " + currentPath);
				System.out.println();
				findAllIndexesForPathOccurence(genome.getGenom(), currentPath, superbubbleNumber,
						datasetTmp, pathNumber);
			}

		}
		dataset = datasetTmp;
	}

	private static String convertPathToGenomeSubString(String path) {
		StringBuilder builder = new StringBuilder();
		StringTokenizer stringTokenizer = new StringTokenizer(path.trim(), " ");
		builder.append(stringTokenizer.nextToken().trim());
		while (stringTokenizer.hasMoreTokens()) {
			String token = stringTokenizer.nextElement().toString().trim();
			builder.append(token.charAt(token.length() - 1));
		}
		return builder.toString();
	}

	private static void findAllIndexesForPathOccurence(String genome, String path,
			long superbubbleNumber, XYSeriesCollection datasetTmp, long pathNumber) {
		Map<Integer, Integer> indexMap = new HashMap<>();
		int pathLength = path.length();
		int currentRightBorder = 0;
		int occurence = 0;
		while (currentRightBorder < genome.length()) {
			int index = genome.indexOf(path, currentRightBorder);
			if (index == -1) {
				return;
			} else {
				occurence++;
				currentRightBorder = index + pathLength - 1;
				indexMap.put(index, currentRightBorder);
				System.out.println("[ " + index + " ; " + currentRightBorder + " ]");
				XYSeries series = new XYSeries("Superbubble # " + superbubbleNumber+ " and Path #" + pathNumber+"occurnce #" + occurence);
				series.add(index, superbubbleNumber);
				series.add(currentRightBorder, superbubbleNumber);
				datasetTmp.addSeries(series);
			}
		}

	}
}
